import React, { HTMLAttributes, ReactNode, useCallback, useEffect, useRef, useState } from 'react'; import styled from 'styled-components'; import Button from '../Button/Button'; import Left from '../icons/left.svg'; import Right from '../icons/right.svg'; import DoubleLeft from '../icons/doubleLeft.svg'; export interface PaginationProps extends HTMLAttributes { defaultPage?: number; totalSrc: number; perPage?: number; moreTool?: boolean; goTool?: boolean; statistic?: boolean; callback?: (currentPage: number, start: number, end: number) => void; } const PaginationStyled = styled.div` display: flex; align-items: center; gap: 8px; `; const PageButton = styled(Button).attrs({ type: 'text', radius: true, border: 'none' })` height: 2em; min-width: 2em; padding: 0 2px; border: 1px solid #d9d9d9; outline: none; box-shadow: none; &:hover { -webkit-filter: brightness(100%); border: 1px solid #1890ff; } `; const PageWrap = styled.div` display: flex; align-items: center; gap: 8px; `; const InputStyled = styled.input` max-width: 4em; height: 2em; outline: none; border: 1px solid #d9d9d9; border-radius: 2px; padding: 10px; &:focus { border: 1px solid #1890ff; box-shadow: 0 0 4px 1px rgba(24, 144, 255, 0.2); } `; type MoreProps = Pick; const MoreStyled = styled(PageButton)` display: ${(props: MoreProps) => (props.moreTool ? 'inline-flex' : 'none')}; `; const GoStyled = styled.div` display: ${(props: MoreProps) => (props.goTool ? 'inline-flex' : 'none')}; gap: 8px; align-items: center; `; const Pagination: React.FC = (props) => { const { children, statistic, goTool, moreTool, perPage, callback, defaultPage, totalSrc, ...rest } = props; const totalPage = Math.ceil(Math.abs(totalSrc!) / perPage!); const [n, setN] = useState(1); // 当前处于那一页 const pageWrap = useRef(null); const inputRef = useRef(null); const dom: ReactNode[] = []; useEffect(() => { setN(Math.abs(defaultPage! > totalPage ? 1 : defaultPage!)); }); // eslint-disable-next-line consistent-return const createPageNumber = (i: number): number => { let endPage = 0; if (totalPage <= 5) { endPage = i + 1; } if (totalPage > 5 && n <= 5) { endPage = i + 1; } if (totalPage > 5 && n > 5) { endPage = n - 2 + i; if (n + 5 > totalPage) { endPage = n - 4 + i; } } return endPage; }; // 初始化 for (let i = 0; i < (totalPage > 5 ? 5 : totalPage); i++) { dom.push({createPageNumber(i)}); } const call = useCallback((numberPage: number) => { if (perPage) { let start: number; let end: number; if (numberPage === 1) { start = 0; } else { start = perPage * numberPage - perPage; } if (perPage * numberPage > totalSrc) { end = totalSrc; } else { end = perPage * numberPage; } callback?.(numberPage, start, end); } }, []); // 左侧被点击 const leftClick = () => { if (n > 1) { setN((state) => state - 1); call(n - 1); } }; // 右侧被点击 const rightClick = () => { if (n < totalPage) { setN(() => n + 1); call(n + 1); } }; // page点击 const WrapClick = (e: React.MouseEvent) => { const el = e.target as HTMLButtonElement; if (el.tagName.toLowerCase() === 'button') { const numberPage = parseInt(el.innerText, 10); setN(numberPage); call(numberPage); } }; // 更多被点击 const moreClick = () => { if (n + 5 < totalPage) { setN(() => n + 5); call(n + 5); } else if (n === totalPage) { return null; } else { setN(totalPage); call(totalPage); } }; // 输入新的页码 const inputNewPageNumber = () => { if (inputRef.current?.value) { const pageNumber = parseInt(inputRef.current?.value, 10) || 1; if (pageNumber >= totalPage && pageNumber) { setN(totalPage); call(totalPage); } else { setN(pageNumber); call(pageNumber); } } }; useEffect(() => { if (pageWrap.current) { const childList = Array.from(pageWrap.current.children as unknown as HTMLButtonElement[]); childList.forEach((item) => { if (item.innerText === n.toString()) { item.style.color = '#1890ff'; } }); } }); return ( ) => { WrapClick(e); }} role="presentation" > {dom} = totalPage ? 'not-allowed' : 'pointer', border: 'none', backgroundColor: 'inherit', display: moreTool ? 'block' : 'none' }} > = totalPage ? 'not-allowed' : 'pointer' }} > 跳至 {n}/{totalPage} ); }; Pagination.defaultProps = { defaultPage: 1, callback: () => {}, perPage: 5, moreTool: false, statistic: false, goTool: false }; export default React.memo(Pagination);